﻿using System;
using System.Web.Mvc;
using Contrib.FeedsAggregator.Models;
using Contrib.FeedsAggregator.Services;
using Orchard;
using Orchard.ContentManagement;
using Orchard.Core.Contents.Controllers;
using Orchard.Localization;
using Orchard.UI.Admin;
using Orchard.UI.Notify;

namespace Contrib.FeedsAggregator.Controllers {
    [Admin]
    public class AdminController : Controller, IUpdateModel {
        private readonly IFeedsService _feedsService;

        public AdminController(
            IOrchardServices services,
            IFeedsService feedsService) {

            Services = services;
            _feedsService = feedsService;

            T = NullLocalizer.Instance;
        }

        private IOrchardServices Services { get; set; }
        public Localizer T { get; set; }

        public ActionResult Index() {
            if (!Services.Authorizer.Authorize(Permissions.ManageFeeds, T("Not allowed to manage feeds")))
                return new HttpUnauthorizedResult();

            return View(_feedsService.GetFeeds());
        }

        public ActionResult Create() {
            try {
                if (!Services.Authorizer.Authorize(Permissions.ManageFeeds, T("Not allowed to manage feeds")))
                    return new HttpUnauthorizedResult();

                FeedPart feedPart = Services.ContentManager.New<FeedPart>("Feed");
                if (feedPart == null)
                    return HttpNotFound();

                dynamic model = Services.ContentManager.BuildEditor(feedPart);
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }
            catch (Exception exception) {
                Services.TransactionManager.Cancel();
                Services.Notifier.Error(T("Creating feed failed: {0}", exception.Message));
                return RedirectToAction("Index", "Admin");
            }
        }

        [HttpPost, ActionName("Create")]
        public ActionResult CreatePOST(string feedUrl) {
            try {
                if (!Services.Authorizer.Authorize(Permissions.ManageFeeds, T("Not allowed to manage feeds")))
                    return new HttpUnauthorizedResult();

                
                if (!_feedsService.IsValidFeedUrl(feedUrl)) {
                    throw new OrchardException(T("Invalid feed"));
                }

                FeedPart feedPart = Services.ContentManager.Create<FeedPart>("Feed");
                dynamic model = Services.ContentManager.UpdateEditor(feedPart, this);
                if (!ModelState.IsValid || feedUrl != feedPart.FeedUrl) {
                    Services.TransactionManager.Cancel();
                    // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                    return View((object)model);
                }

                Services.Notifier.Information(T("Feed was successfully created"));
                return RedirectToAction("Index");
            }
            catch (Exception exception) {
                Services.TransactionManager.Cancel();
                Services.Notifier.Error(T("Creating feed failed: {0}", exception.Message));
                return RedirectToAction("Index", "Admin");
            }
        }

        public ActionResult Edit(int id) {
            try {
                if (!Services.Authorizer.Authorize(Permissions.ManageFeeds, T("Not allowed to manage feeds")))
                    return new HttpUnauthorizedResult();

                FeedPart feedPart = _feedsService.GetFeed(id);
                if (feedPart == null)
                    return HttpNotFound();

                dynamic model = Services.ContentManager.BuildEditor(feedPart);
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }
            catch (Exception exception) {
                Services.TransactionManager.Cancel();
                Services.Notifier.Error(T("Editing feed failed: {0}", exception.Message));
                return RedirectToAction("Index", "Admin");
            }
        }

        [HttpPost, ActionName("Edit")]
        [FormValueRequired("submit.Save")]
        public ActionResult EditSavePOST(int id) {
            try {
                if (!Services.Authorizer.Authorize(Permissions.ManageFeeds, T("Not allowed to manage feeds")))
                    return new HttpUnauthorizedResult();

                FeedPart feedPart = _feedsService.GetFeed(id);
                if (feedPart == null)
                    return HttpNotFound();

                dynamic model = Services.ContentManager.UpdateEditor(feedPart, this);
                if (!ModelState.IsValid) {
                    Services.TransactionManager.Cancel();
                    // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                    return View((object)model);
                }

                Services.Notifier.Information(T("Feed information updated"));
                return RedirectToAction("Index");
            }
            catch (Exception exception) {
                Services.TransactionManager.Cancel();
                Services.Notifier.Error(T("Editing feed failed: {0}", exception.Message));
                return RedirectToAction("Index", "Admin");
            }
        }

        [HttpPost, ActionName("Edit")]
        [FormValueRequired("submit.Delete")]
        public ActionResult EditDeletePOST(int id) {
            return Delete(id);
        }

        public ActionResult Delete(int id) {
            try {
                if (!Services.Authorizer.Authorize(Permissions.ManageFeeds, T("Not allowed to manage feeds")))
                    return new HttpUnauthorizedResult();

                _feedsService.DeleteFeed(id);

                Services.Notifier.Information(T("Feed was successfully deleted"));
                return RedirectToAction("Index");
            }
            catch (Exception exception) {
                Services.TransactionManager.Cancel();
                Services.Notifier.Error(T("Deleting feed failed: {0}", exception.Message));
                return RedirectToAction("Index", "Admin");
            }
        }

        bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
            return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
        }

        void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
            ModelState.AddModelError(key, errorMessage.ToString());
        }
    }
}